#include <Network.h>
#include <QDebug>
Network::Network(QString hostname, QString AETitle, int port, int timeout) {
  scu = new gdcm::ServiceClassUser;
  scu->SetHostname(hostname.toUtf8());
//  scu->SetHostname("213.165.94.158");
  //scu->SetHostname("184.73.255.26");
  scu->SetTimeout( timeout );
  scu->SetPort( port );
  scu->SetAETitle(AETitle.toUtf8());
  if( !scu->InitializeConnection() ) {
    qDebug() <<  "Could not initialize connection!";
  }
}

bool Network::Echo() {
  bool value = false;
  if( !generator.GenerateFromUID(gdcm::UIDs::GeneralRelevantPatientInformationQuery) ) {
    std::cerr << "Could not Generate From UID" << std::endl;
    return value;
  }
  if( Start() ) {
    if( scu->SendEcho() ) {
      qDebug() << "ECHO sent!";
      value = true;
    } else {
      qDebug() << "Could not send ECHO!";
    }
    Stop();
  }
  return value;
}

bool Network::Find() {
  if( !generator.GenerateFromUID(gdcm::UIDs::PatientRootQueryRetrieveInformationModelFIND) ) {
    std::cerr << "Could not Generate From UID" << std::endl;
    return false;
  }
  bool value = false;
  if( Start() ) {
    std::vector< gdcm::DataSet > datasets;
    gdcm::FindPatientRootQuery query;
    query.InitializeDataSet(gdcm::ePatient);
    //gdcm::SmartPointer<gdcm::BaseRootQuery> query = gdcm::QueryFactory::ProduceQuery(   gdcm::ePatientRootType,gdcm::eFind,gdcm::eStudy);
    if( scu->SendFind( &query, datasets ) ) {
      qDebug() << "FIND sent!";
      value = true;
      qDebug() << "Received " << datasets.size() << " datasets!";
      foreach (gdcm::DataSet ds, datasets) {
        std::cout << ds << std::endl;
      }
    } else {
      qDebug() << "Could not send FIND!";
    }
    Stop();
  }
  return value;
}

bool Network::Store(const QString &filename) {
  if(filename.isEmpty()) {
    qDebug() << "Invalid filename!";
    return false;
  }
  gdcm::Directory::FilenamesType filenames;
  filenames.push_back( filename.toStdString().c_str() );
  if( !generator.GenerateFromFilenames(filenames) ) {
    std::cerr << "Could not Generate From Filenames" << std::endl;
    return false;
  }
  bool value = false;
  if( Start()) {
    if( scu->SendStore(filename.toUtf8()) ) {
      qDebug() << "C-STORE sent";
      value = true;
    } else {
      qDebug() << "Could not send C-STORE!";
    }
    Stop();
  }
  return value;
}

bool Network::Move() {
  if( !generator.GenerateFromUID(gdcm::UIDs::PatientRootQueryRetrieveInformationModelMOVE) ) {
    std::cerr << "Could not Generate From UID" << std::endl;
    return false;
  }
  bool value = false;

  if(Start()) {

    //gdcm::SmartPointer<gdcm::BaseRootQuery> query = gdcm::QueryFactory::ProduceQuery(gdcm::ePatientRootType,gdcm::eMove,gdcm::eImage);

    gdcm::MovePatientRootQuery query;
    query.InitializeDataSet(gdcm::eImage);
    std::vector< gdcm::DataSet > datasets;

    if( scu->SendMove(&query, datasets) ) {
      qDebug() << "MOVE sent!";
      qDebug() << "Received " << datasets.size() << " datasets!";
      foreach (gdcm::DataSet ds, datasets) {
        std::cout << ds << std::endl;
      }
      value = true;
    } else {
      qDebug() << "Could not send MOVE!";
      value = false;
    }

    std::vector< gdcm::File > files;
    if( scu->SendMove(&query, files) ) {
      qDebug() << "MOVE sent!";
      qDebug() << "Received " << files.size() << " files!";
      foreach (gdcm::File file, files) {
        std::cout << file << std::endl;
      }
      value = true;
    } else {
      qDebug() << "Could not send MOVE!";
      value = false;
    }

    if( !scu->SendMove(&query, "/tmp/gdcm") ) {
      qDebug() << "MOVE sent!";
      value = true;
    } else {
      qDebug() << "Could not send MOVE!";
      value = false;
    }
    Stop();
  }
  return value;
}

bool Network::Start() {
  scu->SetPresentationContexts( generator.GetPresentationContexts() );
  if( scu->StartAssociation() )
    return true;
  qDebug() << "Could not Start Association!";
  return false;
}

bool Network::Stop() {
  if( scu->StopAssociation() ) {
    qDebug() << "Association Stopped";
    return true;
  }
  qDebug() << "Could not Stop";
  return false;
}
